﻿using System;
using System.Configuration;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Routing;
using Web7.Configuration;
using Web7.Core.ActionFilters.Result;
using Web7.Core.Apps;
using Web7.Core.BootStrapperTask;
using Web7.Core.BootStrapperTasks;
using Web7.Core.Configuration;
using Web7.Core.Context;
using Web7.Core.ControllerFactories;
using Web7.Core.Sites;
using Web7.Core.ViewEngine;
using Web7.FilterProviders;
using Web7.Ioc;
using Web7.Mvc.ViewEngines;
using Web7.RouteUrlModifiers;
using Web7.Utilities;
using NHibernate;
using Web7.Mvc.ActionInvokers;

namespace Web7.Core
{
    /// <summary>
    /// web7依赖容器管理
    /// </summary>
    /// <typeparam name="TWebApp"></typeparam>
    public class Web7ContainerBuilder<TWebApp> : IDependencyDemandBuilder
        where TWebApp : HttpApplication
    {
        #region Private fields

        //private readonly IComponentRegistrar _componentRegistrar;
        //private readonly Web7Settings _settings;
        private readonly HttpApplication _httpApp;
        private readonly object _locker = new object();

        #endregion
        /// <summary>
        /// 默认构造Web7ComponentRegistrar作为IComponentRegistrar使用的标准
        /// </summary>
        /// <param name="httpApp"></param>
        public Web7ContainerBuilder(TWebApp httpApp)
        {
            _httpApp = httpApp;
            //_settings = Web7Settings.GetSettings();
            //_componentRegistrar = new Web7ComponentRegistrar();
        }

        #region Events

        /// <summary>
        /// 建立依赖关系之前（Build）.允许开发人员在容器中注册（事件）自己的对象
        /// </summary>
        public event EventHandler<ContainerBuilderEventArgs> ContainerBuilding;

        /// <summary>
        ///建立依赖关系成功后（Build）.允许开发人员在容器中注册（事件）自己的对象
        /// </summary>
        public event EventHandler<ContainerBuilderEventArgs> ContainerBuildingComplete;

        #endregion


        #region Protected event raising methods

        /// <summary>
        /// 建立依赖关系之前（Build）.
        /// </summary>
        /// <param name="args"></param>
        protected void OnContainerBuilding(ContainerBuilderEventArgs args)
        {
            if (ContainerBuilding != null)
            {
                ContainerBuilding(this, args);
            }
        }
        /// <summary>
        /// 建立依赖关系成功后（Build）.
        /// </summary>
        /// <param name="args"></param>
        protected void OnContainerBuildingComplete(ContainerBuilderEventArgs args)
        {
            if (ContainerBuildingComplete != null)
            {
                ContainerBuildingComplete(this, args);
            }
        }

        #endregion

        /// <summary>
        /// 建立需要用到的依赖要求。
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="context"></param>
        public void Build(IWeb7ContainerBuilder builder, IBuilderContext context)
        {
            //building event
            OnContainerBuilding(new ContainerBuilderEventArgs(builder));

            //todo:register all of the abstract web types
            //builder.AddDependencyDemandBuilder(new WebTypesDemandBuilder(_httpApp)); //todo:httpapplication 这一块的注册

            #region 注册已有对象实例为单例
            var typeFinder = new TypeFinder();
            builder.ForInstanceOfType(typeFinder).ScopedAs.Singleton();

            // Web7ConfigurationSection为自定义配置节点，用于配置Module信息
            builder.ForInstanceOfType((Web7ConfigurationSection)ConfigurationManager.GetSection("web7")).ScopedAs.Singleton();
            //web7应用程序配置注册
            builder.For<Web7Settings>().KnownAsSelf().ScopedAs.Singleton();

            builder.For<DefaultWeb7ApplicationContext>().KnownAs<IWeb7ApplicationContext>().ScopedAs.Singleton(); //web应用程序上下文

            // AppSettingsHelper对web.config的appSettings节点进行封装
            builder.ForInstanceOfType(new AppSettingsHelper(ConfigurationManager.AppSettings)).ScopedAs.Singleton();

            // RouteCollection，全局的静态的路由表
            builder.ForFactory(x => RouteTable.Routes).ScopedAs.Singleton();

            // ModelBinderDictionary，通过请求数据(QueryString、Form、RouteValue等)生成实体
            builder.ForFactory(x => ModelBinders.Binders).ScopedAs.Singleton();
            // ViewEngineCollection，视图引擎集合
            builder.ForFactory(x => ViewEngines.Engines).ScopedAs.Singleton();
            // GlobalFilterCollection，全局拦截器集合，本身也是拦截器提供器
            builder.ForFactory(x => GlobalFilters.Filters).ScopedAs.Singleton();
            // FilterProviderCollection 拦截器提供器集合
            builder.ForFactory(x => System.Web.Mvc.FilterProviders.Providers).ScopedAs.Singleton();
            // VirtualPathProvider 虚拟路径提供器
            builder.ForFactory(x => HostingEnvironment.VirtualPathProvider).ScopedAs.Singleton();

            // ModulesLoaded 相当于一个容器类，用于加载指定模块(Module)，并用一个集合保存之
            //builder.ForInstanceOfType<IAppRegistry>(new AppRegistry(builder)).ScopedAs.Singleton(); //todo:解决注册获取顺序问题。 先让你编译报错

            // FilterRegistryFilterProvider Filter注册表Filter提供器
            builder.ForFactory<IFilterProvider>(x => new FilterRegistryFilterProvider(x));

            // LoadModules引导程序，根据Web7.config中modules节点的配置，对模块进行注册
            // LoadBackgroundServices引导程序，加载后台服务
            builder.ForFactory<IBootStrapperTask>(x => new LoadApps(x));//"LoadApps",

            builder.ForFactory<IBootStrapperTask>(x => new LoadBackgroundServices(x));//"LoadBackgroundServices",//todo:中途注入的问题

            #endregion

            // RouteUrlModifier 用于给Route路径加前缀(目的是为了兼容默认配置下的IIS5.1以及IIS6)
            builder.For<RouteUrlModifier>().KnownAs<IRouteUrlModifier>();
            // 系统(站点)配置信息处理逻辑
            builder.For<SiteService>().KnownAs<ISiteService>();


            //APP注册模块
            builder.AddDependencyDemandBuilder(new AppManagement());

            #region
            builder.For<WebFormViewEngineProvider>().KnownAs<IViewEngineProvider>().ScopedAs.Singleton();
            builder.For<RazorViewEngineProvider>().KnownAs<IViewEngineProvider>().ScopedAs.Singleton();
            builder.For<ViewResultFilter>().KnownAs<IResultFilter>();
            #endregion

            //设置DI映射
            builder.For<Web7ControllerActionInvoker>().KnownAs<IActionInvoker>();

            //NHibernate
            ISessionFactory sessionFactory = new NHibernate.Cfg.Configuration().Configure().BuildSessionFactory();
            builder.ForInstanceOfType<ISessionFactory>(sessionFactory);

            ControllerBuilder.Current.SetControllerFactory(new Web7ControllerFactory());
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new Web7ViewEngine());
        }
    }
}
